package com.ipc.app.dal.dao.impl;

import java.math.BigInteger;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.ipc.app.dal.dao.InformationDAO;
import com.ipc.app.dal.dao.sql.InformationSQL;
import com.ipc.app.dal.doObject.InformationDO;

/**
 * @author haijie.zhang
 * 
 */
public class InformationDAOImpl extends HibernateDaoSupport implements
		InformationDAO {

	public void createInformation(InformationDO informationDO) {
		this.getHibernateTemplate().save(informationDO);
	}

	public InformationDO getInformationById(String informationID) {
		InformationDO informationDO = (InformationDO) this
				.getHibernateTemplate().get(InformationDO.class, informationID);
		return informationDO;
	}

	public InformationDO lockInformation(String informationID) {
		InformationDO informationDO = (InformationDO) this
				.getHibernateTemplate().get(InformationDO.class, informationID,
						LockMode.UPGRADE);
		return informationDO;
	}

	public void updateInformation(InformationDO informationDO) {
		this.getHibernateTemplate().clear();
		this.getHibernateTemplate().update(informationDO);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ipc.app.dal.dao.InformationDAO#getLastestInformationDOByPagerAndCity
	 *      (java.lang.String, int, int)
	 */
	@SuppressWarnings("unchecked")
	public List<InformationDO> getLastestInformationDOByPagerAndCity(
			final String city, final String informationType,
			final int pageNumber, final int pagerIndex) {
		List<InformationDO> informationDOs = (List<InformationDO>) this
				.getHibernateTemplate().execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String sql = InformationSQL
								.getInformationDOByPagerAndCity(
										informationType, city);
						Query query = session.createSQLQuery(sql).addEntity(
								InformationDO.class);
						query.setFirstResult(pageNumber * (pagerIndex - 1));
						query.setMaxResults(pageNumber);
						List<InformationDO> informationDOs = query.list();
						return informationDOs;
					}
				});

		return informationDOs;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ipc.app.dal.dao.InformationDAO#getInformationCountByCity(java.lang
	 *      .String)
	 */
	public int getInformationCountByCity(final String city,
			final String informationType) {
		Integer totalInformation = (Integer) this.getHibernateTemplate()
				.execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String sql = InformationSQL
								.queryInformationCountByCity(informationType,
										city);
						Query query = session.createSQLQuery(sql);
						BigInteger count = (BigInteger) query.uniqueResult();
						return count.intValue();
					}
				});
		return totalInformation;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ipc.app.dal.dao.InformationDAO#getInformationBetween2City(java.lang
	 *      .String, java.lang.String, int, int)
	 */
	@SuppressWarnings("unchecked")
	public List<InformationDO> getInformationBetween2City(
			final String departure, final String destination,
			final String informationType, final int pageNumber,
			final int pagerIndex) {

		List<InformationDO> informationDOs = (List<InformationDO>) this
				.getHibernateTemplate().execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String sql = InformationSQL
								.getInformationBetween2Cities(informationType,
										departure, destination);
						Query query = session.createSQLQuery(sql).addEntity(
								InformationDO.class);
						query.setFirstResult(pageNumber * (pagerIndex - 1));
						query.setMaxResults(pageNumber);
						List<InformationDO> informationDOs = query.list();
						return informationDOs;
					}
				});
		return informationDOs;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ipc.app.dal.dao.InformationDAO#getInformationCountBetweenCities(java
	 *      .lang.String, java.lang.String)
	 */
	public int getInformationCountBetweenCities(final String departure,
			final String destination, final String informationType) {
		Integer totalInformation = (Integer) this.getHibernateTemplate()
				.execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String sql = InformationSQL
								.queryInformationCountBetween2Cities(
										informationType, departure, destination);
						Query query = session.createSQLQuery(sql);
						BigInteger count = (BigInteger) query.uniqueResult();
						return count.intValue();
					}
				});
		return totalInformation;
	}

	public int getRoundInformationCount(final Double startX, final Double endX,
			final Double startY, final Double endY, final String informationType) {
		Integer totalInformation = (Integer) this.getHibernateTemplate()
				.execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String sql = InformationSQL.getRoundInformationCount(
								informationType, startX, endX, startY, endY);
						Query query = session.createSQLQuery(sql);
						BigInteger count = (BigInteger) query.uniqueResult();
						return count.intValue();
					}
				});
		return totalInformation;
	}

	@SuppressWarnings("unchecked")
	public List<InformationDO> getRoundInformation(final Double startX,
			final Double endX, final Double startY, final Double endY,
			final String informationType, final int pageNumber,
			final int pagerIndex) {
		List<InformationDO> informationDOs = (List<InformationDO>) this
				.getHibernateTemplate().execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String sql = InformationSQL.getRoundInformation(
								informationType, startX, endX, startY, endY);
						Query query = session.createSQLQuery(sql).addEntity(
								InformationDO.class);
						query.setFirstResult(pageNumber * (pagerIndex - 1));
						query.setMaxResults(pageNumber);
						List<InformationDO> informationDOs = query.list();
						return informationDOs;
					}
				});
		return informationDOs;
	}

	public int getInformationByDepAndDesCount(final Double dep_startX,
			final Double dep_endX, final Double dep_startY,
			final Double dep_endY, final Double des_startX,
			final Double des_endX, final Double des_startY,
			final Double des_endY, final String informationType,
			final int pageNumber, final int pagerIndex) {
		Integer totalInformation = (Integer) this.getHibernateTemplate()
				.execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session
								.getNamedQuery("getInformationByDepAndDesCount");
						query.setParameter("dep_startX", dep_startX);
						query.setParameter("dep_endX", dep_endX);
						query.setParameter("dep_startY", dep_startY);
						query.setParameter("dep_endY", dep_endY);
						query.setParameter("des_startX", des_startX);
						query.setParameter("des_endX", des_endX);
						query.setParameter("des_startY", des_startY);
						query.setParameter("des_endY", des_endY);
						query.setParameter("informationType", informationType);
						BigInteger count = (BigInteger) query.uniqueResult();
						return count.intValue();
					}
				});
		return totalInformation;
	}

	@SuppressWarnings("unchecked")
	public List<InformationDO> getInformationByDepAndDes(
			final Double dep_startX, final Double dep_endX,
			final Double dep_startY, final Double dep_endY,
			final Double des_startX, final Double des_endX,
			final Double des_startY, final Double des_endY,
			final String informationType, final int pageNumber,
			final int pagerIndex) {
		List<InformationDO> informationDOs = (List<InformationDO>) this
				.getHibernateTemplate().execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session
								.getNamedQuery("getInformationByDepAndDes");
						query.setParameter("dep_startX", dep_startX);
						query.setParameter("dep_endX", dep_endX);
						query.setParameter("dep_startY", dep_startY);
						query.setParameter("dep_endY", dep_endY);
						query.setParameter("des_startX", des_startX);
						query.setParameter("des_endX", des_endX);
						query.setParameter("des_startY", des_startY);
						query.setParameter("des_endY", des_endY);
						query.setParameter("informationType", informationType);
						query.setFirstResult(pageNumber * (pagerIndex - 1));
						query.setMaxResults(pageNumber);
						List<InformationDO> informationDOs = query.list();
						return informationDOs;
					}
				});
		return informationDOs;
	}

	public int getInformationCountByUserId(final String userID,
			final String informationType) {
		Integer totalInformation = (Integer) this.getHibernateTemplate()
				.execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session
								.getNamedQuery("getUserInformationCount");
						query.setParameter("user_id", userID);
						query.setParameter("informationType", informationType);
						BigInteger count = (BigInteger) query.uniqueResult();
						return count.intValue();
					}
				});
		return totalInformation;
	}

	@SuppressWarnings("unchecked")
	public List<InformationDO> getInformationByUserID(final String userID,
			final String informationType, final int pageNumber,
			final int pageIndex) {
		List<InformationDO> informationDOs = (List<InformationDO>) this
				.getHibernateTemplate().execute(new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session
								.getNamedQuery("getUserInformation");
						query.setParameter("user_id", userID);
						query.setParameter("informationType", informationType);
						query.setFirstResult(pageNumber * (pageIndex - 1));
						query.setMaxResults(pageNumber);
						List<InformationDO> informationDOs = query.list();
						return informationDOs;
					}
				});
		return informationDOs;
	}

	@SuppressWarnings("unchecked")
	public void setExpiredInformation(final String status) {
		this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				String sql = InformationSQL.updateExpiredInformation(status,
						new Date());
				session.createSQLQuery(sql).executeUpdate();
				return null;
			}
		});
	}
}
